---
title: HTTP cache
---


> This page focuses on the HTTP cache. If you want to deduplicate the storage of your objects and/or notify your UI when your data changes, take a look at the [normalized cache](./normalized-cache) instead.

<Note>

HTTP caching is only available on the JVM.

</Note>

Apollo uses OkHttp's [cacheUrlOverride](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-request/-builder/cache-url-override.html) to cache GraphQL POST requests when [persisted queries](https://www.apollographql.com/docs/kotlin/advanced/persisted-queries) and GET requests are not an option.

## Setup

Configure your `NetworkTransport` with your cache-enabled `OkHttpClient` and `cachePostRequests` set to `true`:

```kotlin
  val apolloClient = ApolloClient.Builder()
    .networkTransport(
        HttpNetworkTransport.Builder()
            // Enable POST caching
            .httpRequestComposer(DefaultHttpRequestComposer(serverUrl = serverUrl, enablePostCaching = true))
            .httpEngine(
                DefaultHttpEngine {
                  OkHttpClient.Builder()
                      .cache(directory = File(application.cacheDir, "http_cache"), maxSize = 10_000_000)
                      .build()
                }
            )
            .build()
    )
    .build()
```

Under the hood, the OkHttp `HttpEngine` uses `"${url}?variablesHash=${variables.sha256()}&operationName=${operation.name()}&operationId=${operation.id()}"` as a <code>cacheUrlOverride</code> to cache POST requests.

## Usage

OkHttp uses the [cache-control header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control):

```kotlin
  val successResponse = MockResponse.Builder()
    .body(FooQuery.successResponse)
    .addHeader("cache-control", "max-age=100")
    .build()
mockServer.enqueue(successResponse)

// first query: goes to the network and caches the response
val response1 = apolloClient.query(FooQuery()).execute()
println(response1.isFromHttpCache) // false
// second query: uses the cached response
val response2 = apolloClient.query(FooQuery()).execute()
println(response2.isFromHttpCache) // true
```

You can use `ApolloResponse.isFromHttpCache` to determine if a given request comes from the cache:

```kotlin
  val response = apolloClient.query(FooQuery()).execute()
assertEquals(false, response.isFromHttpCache)
```

To disable caching for a particular request, use standard HTTP headers. For example, you can use `no-store` to disable storing a response:

```kotlin
  val response1 = apolloClient.query(FooQuery())
    .addHttpHeader("cache-control", "no-store") // this response is not stored
    .execute()
assertEquals(false, response1.isFromHttpCache)
val response2 = apolloClient.query(FooQuery()) // a new HTTP request is issued.
    .execute()
assertEquals(false, response2.isFromHttpCache)
```
